package com.netease.dragonwar.ui;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.*;

import javax.swing.JPanel;

import com.netease.dragonwar.common.GameDirectionEnum;
import com.netease.dragonwar.common.GameStatusEnum;
import com.netease.dragonwar.sprite.Bullet;
import com.netease.dragonwar.sprite.Enemy;
import com.netease.dragonwar.sprite.Hero;
import com.netease.dragonwar.common.Constant;
import com.netease.dragonwar.util.ImageUtils;

/**
 * @author louxj424
 * @date 创建时间：2018年3月4日 下午8:34:50
 * @version 0.1.0
 * @since jdk 1.7.0
 */
public class GamePanel extends JPanel {
	/**
	 * 定义英雄对象
	 */
	private Hero hero;

	/**
	 * 定义定时器对象
	 */
	private Timer timer;

	/**
	 * 游戏状态
	 */
	private GameStatusEnum status;

	/**
	 * 定义用于记录定时器的执行时间
	 */
	private long milliseconds;

	/**
	 *  记录游戏得分
	 */
	private int score;

	/**
	 * 定义背景图片
	 */
	private  BufferedImage backImage = ImageUtils.getBackImage();

	/**
	 * 定义游戏标题图片
	 */
	private  BufferedImage titleImage = ImageUtils.getTitleImage();

	/**
	 * 定义开始按钮图片
	 */
	private  BufferedImage startImage = ImageUtils.getStartImage();

	/**
	 * 定义结束图片
	 */
	private  BufferedImage overImage = ImageUtils.getOverImage();

	/**
	 * 定义重新开始图片
	 */
	private  BufferedImage restartImage = ImageUtils.getRestartImage();

	/**
	 * 定义存储子弹的数据结构
	 */
	private List<Bullet> bullets;

	/**
	 * 定义存储敌人的数据结构
	 */
	private List<Enemy> enemys;

	/**
	 * 游戏的初始化操作
	 */
	public void gameInit() {
		// 初始化定时器的执行时间
		milliseconds = 0;

		// 游戏得分初始化
		score = 0;

		// 初始化英雄，恢复英雄属性设置为默认值
		hero = Hero.getInstance();

		// 初始化子弹数据结构
		bullets = new LinkedList<Bullet>();

		// 初始化敌人数据结构
		enemys = new LinkedList<Enemy>();

		// 清除所有的键盘按键监听器
		KeyListener[] ks = this.getKeyListeners();
		for (int i = 0; i < ks.length; i++) {
			// 移除键盘按键监听器
			this.removeKeyListener(ks[i]);
		}

		// 清除所有的鼠标事件监听器
		MouseMotionListener[] ms = this.getMouseMotionListeners();
		for (int i = 0; i < ms.length; i++) {
			// 移除鼠标移动监听器
			this.removeMouseMotionListener(ms[i]);
		}
	}

	/**
	 * 游戏的准备阶段
	 */
	public void gamePrepare() {
		status = GameStatusEnum.GAME_PREPARE;
		repaint();
		this.setFocusable(true);
		this.requestFocus();
		this.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_SPACE) {
					if (status == GameStatusEnum.GAME_PREPARE || status == GameStatusEnum.GAME_OVER) {
						gameStart();
					}
				}
			}
		});
	}

	/**
	 * 游戏开始
	 */
	public void gameStart() {
		// 修改当前的游戏状态
		status = GameStatusEnum.GAME_RUNNING;

		// 游戏开始先执行初始化操作
		this.gameInit();

		// 设置面板可以获得焦点
		this.setFocusable(true);

		// 让当前面板获得焦点
		this.requestFocus();

		// 初始化定时器对象
		timer = new Timer();
		timer.schedule(new TimerTask() {

			@Override
			public void run() {
				if (milliseconds % 150 == 0) {
					// 英雄摆动
					hero.flicker();

					// 发射子弹
					heroShoot();

					// 清除越界精灵
					clearOutsideSprites();
				}			
				
				if (milliseconds % 50 == 0) {
					// 英雄移动
					heroMove();

					// 子弹移动
					bulletMove();

					// 敌人移动
					enemyMove();

					// 检测子弹与敌人的碰撞
					checkBulletHitEnemy();

					// 检测敌人与英雄的碰撞
					checkEnemyHitHero();
				}

				// 敌人出现
				if (milliseconds % 1000 == 0) {
					enemyEnter();
				}

				// 重新绘制
				repaint();

				// 修改计时器的值
				milliseconds += 10;
			}
		}, 0, 10);

		// 给面板添加鼠标移动的监听事件
		this.addMouseMotionListener(new MouseMotionListener() {

			@Override
			public void mouseMoved(MouseEvent e) {
				int distanceX = e.getX() - hero.getX();
				int distanceY = e.getY() - hero.getY();
				if (Math.abs(distanceX) > Math.abs(distanceY)) {
					if (distanceX > 0) {
						// 设置英雄方向朝右
						hero.setDirection(GameDirectionEnum.DIRECTION_RIGHT);
					} else {
						// 设置英雄方向朝左
						hero.setDirection(GameDirectionEnum.DIRECTION_LEFT);
					}
				} else {
					if (distanceY > 0) {
						// 设置英雄方向朝下
						hero.setDirection(GameDirectionEnum.DIRECTION_DOWN);
					} else {
						// 设置英雄方向朝上
						hero.setDirection(GameDirectionEnum.DIRECTION_UP);
					}
				}
			}

			@Override
			public void mouseDragged(MouseEvent e) {
			}
		});

		// 给面板添加键盘监听事件
		this.addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				switch (e.getKeyCode()) {
				case KeyEvent.VK_UP:
				case KeyEvent.VK_W:
					hero.setOffsetY(0);
					break;
				case KeyEvent.VK_RIGHT:
				case KeyEvent.VK_D:
					hero.setOffsetX(0);
				case KeyEvent.VK_DOWN:
				case KeyEvent.VK_S:
					hero.setOffsetY(0);
				case KeyEvent.VK_LEFT:
				case KeyEvent.VK_A:
					hero.setOffsetX(0);
				default:
					break;
				}
			}

			@Override
			public void keyPressed(KeyEvent e) {
				switch (e.getKeyCode()) {
				case KeyEvent.VK_UP:
				case KeyEvent.VK_W:
					hero.setOffsetY(-1 * hero.getSpeed());
					break;
				case KeyEvent.VK_RIGHT:
				case KeyEvent.VK_D:
					hero.setOffsetX(1 * hero.getSpeed());
					break;
				case KeyEvent.VK_DOWN:
				case KeyEvent.VK_S:
					hero.setOffsetY(1 * hero.getSpeed());
					break;
				case KeyEvent.VK_LEFT:
				case KeyEvent.VK_A:
					hero.setOffsetX(-1 * hero.getSpeed());
					break;
				default:
					break;
				}
			}
		});
	}

	/**
	 * 绘制方法
	 * @param g
	 */
	@Override
	public void paint(Graphics g) {
		// 游戏准备中
		if (status == GameStatusEnum.GAME_PREPARE) {
			g.drawImage(backImage, 0, 0, Constant.WINDOW_WIDTH, Constant.WINDOW_HEIGHT, null);

			g.drawImage(titleImage, 170, 120, 460, 120, null);

			g.drawImage(startImage, 249, 320, 303, 40, null);

		} else {// 游戏开始
				// 绘制游戏背景
			g.drawImage(backImage, 0, 0, Constant.WINDOW_WIDTH, Constant.WINDOW_HEIGHT, null);

			// 绘制英雄
			int x = hero.getX() - hero.getWidth() / 2;
			int y = hero.getY() - hero.getHeight() / 2;
			g.drawImage(hero.getImage(), x, y, hero.getWidth(), hero.getHeight(), null);

			// 绘制子弹：遍历子弹列表，绘制出其中的每个元素
			for (Bullet bullet : bullets) {
				x = bullet.getX() - bullet.getWidth() / 2;
				y = bullet.getY() - bullet.getHeight() / 2;
				g.drawImage(bullet.getImage(), x, y, bullet.getWidth(), bullet.getHeight(), null);
			}

			// 绘制敌人：遍历敌人列表，绘制出其中的每个元素
			for (Enemy enemy : enemys) {
				x = enemy.getX() - enemy.getWidth() / 2;
				y = enemy.getY() - enemy.getHeight() / 2;
				g.drawImage(enemy.getImage(), x, y, enemy.getWidth(), enemy.getHeight(), null);
			}

			// 绘制得分
			g.setColor(new Color(255, 255, 255));
			g.setFont(new Font(Font.SERIF, Font.BOLD, 16));
			// g.drawString(score+"", 10, 20);
			g.drawString(Integer.toString(score), 10, 20);

			if (status == GameStatusEnum.GAME_OVER) {
				g.drawImage(overImage, 160, 150, 480, 50, null);
				g.drawImage(restartImage, 320, 280, 150, 40, null);
			}

		}
	}

	/**
	 * 发射子弹并存储到子弹数组中
	 */
	public void heroShoot() {
		Bullet bullet = hero.shoot();
		bullets.add(bullet);
	}

	/**
	 * 子弹移动
	 */
	public void bulletMove() {
		for (Bullet bullet : bullets) {
			if(! bullet.isOutside())
			{
				bullet.move();
			}
		}
	}

	/**
	 * 英雄移动
	 */
	public void heroMove() {
		hero.move();
	}

	/**
	 * 清除界外的子弹和敌人
	 */
	public void clearOutsideSprites() {
		// 清除越界的子弹
		for (Iterator iterator = bullets.iterator(); iterator.hasNext();) {
			Bullet bullet = (Bullet) iterator.next();
			if (bullet.isOutside()) {
				bullets.remove(iterator);
			}
		}

		// 清除越界的敌人
		for (Iterator iterator = enemys.iterator(); iterator.hasNext();) {
			Enemy enemy = (Enemy) iterator.next();
			if (enemy.isOutside()) {
				enemys.remove(iterator);
			}
		}
	}

	/**
	 * 敌人进入
	 */
	public void enemyEnter() {
		Enemy enemy = null;
		long t = System.currentTimeMillis();
		Random random = new Random(t);
		int randomX = random.nextInt(Constant.WINDOW_WIDTH);
		int randomY = random.nextInt(Constant.WINDOW_HEIGHT);

		GameDirectionEnum [] emumArray= GameDirectionEnum.values();
		GameDirectionEnum direction = emumArray[random.nextInt(emumArray.length)];

		switch (direction) {
		case DIRECTION_UP:
			enemy = new Enemy(randomX, 0, 70, 67, 3);
			break;
		case DIRECTION_RIGHT:
			enemy = new Enemy(Constant.WINDOW_WIDTH, randomY, 70, 67, 3);
			break;
		case DIRECTION_DOWN:
			enemy = new Enemy(randomX, Constant.WINDOW_HEIGHT, 70, 67, 3);
			break;
		case DIRECTION_LEFT:
			enemy = new Enemy(0, randomY, 70, 67, 3);
			break;
		default:
			break;
		}

		enemys.add(enemy);
	}

	/**
	 * 敌人移动
	 */
	public void enemyMove() {

		for (Iterator iterator = enemys.iterator(); iterator.hasNext();) {
			Enemy enemy = (Enemy) iterator.next();
			if(!enemy.isOutside())
			{
				enemy.setTargetX(hero.getX());
				enemy.setTargetY(hero.getY());
				enemy.move();
			}
		}
	}

	/**
	 * 检测子弹碰撞敌人
	 */
	public void checkBulletHitEnemy() {
		for (Iterator iterator = bullets.iterator(); iterator.hasNext();) {
			Bullet bullet = (Bullet) iterator.next();
			for (Iterator iterator2 = enemys.iterator(); iterator2.hasNext();) {
				Enemy enemy = (Enemy) iterator2.next();
				
				if( !bullet.isOutside() && !enemy.isOutside())
				{
					if (bullet.isHit(enemy)) {
						// 通过设置位置将敌人移出
						bullet.setX(1000);
						enemy.setX(1000);

						// 每次击中敌人增加100分
						score += 100;
						
						break;
					}
				}
				
			}
		}

	}

	/**
	 * 检测敌人碰撞英雄
	 */
	public void checkEnemyHitHero() {
		for (Enemy enemy : enemys) {
			if (enemy.isHit(hero)) {
				// 游戏结束
				gameOver();
				break;
			}
		}
	}

	/**
	 * 游戏结束
	 */
	public void gameOver() {
		status = GameStatusEnum.GAME_OVER;
		timer.cancel();
		repaint();
		addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_SPACE) {
					gameStart();
				}
			}
		});
	}
}
